#include "EventloopThreadPool.h"
#include "Eventloop.h"
#include "EventloopThread.h"
#include "utility/assertion.h"

EventloopThreadPool::EventloopThreadPool(Eventloop &loop, std::string name):
    _name{std::move(name)},
    _loopThreads{},
    _baseloop{loop},
    _threadCount{0},
    _next{0},
    _started{false} {}

EventloopThreadPool::~EventloopThreadPool() = default;

void EventloopThreadPool::set_thread_count(std::size_t threadCount) {
    if (_started) {
        return;
    }
    _threadCount = threadCount;
}

Eventloop &EventloopThreadPool::next_loop() {
    _baseloop.ASSERT_IN_THIS_THREAD();
    assert(_started);
    if (_loopThreads.empty()) {
        return _baseloop;
    }
    const auto next = _next;
    if (++_next >= _loopThreads.size()) {
        _next = 0;
    }
    return _loopThreads.at(next)->eventloop();
}

void EventloopThreadPool::init_start(const EventloopThreadInitFunc &initFunc) {
    assert(!_started);
    _baseloop.ASSERT_IN_THIS_THREAD();
    _started = true;
    for (decltype(_threadCount) i = 0; i < _threadCount; ++i) {
        _loopThreads.emplace_back(std::make_unique<EventloopThread>(initFunc, _name + std::to_string(i)));
        _loopThreads.back()->start();
    }
    if (_threadCount == 0) {
        return;
    }
    initFunc(_baseloop);
}

void EventloopThreadPool::start() {
    init_start(default_eventloop_thread_init_func);
}

void EventloopThreadPool::stop() {
    if (_started) {
        return;
    }
    for (const auto &x : _loopThreads) {
        x->stop();
    }
    _started = true;
}

 
